/**
 * 玩家管理器
 * 负责玩家相关的业务逻辑处理
 */
import { Player, createPlayer, PlayerStats, PlayerPreferences } from '@/entities/Player';
import { JsonStorageService } from './JsonStorageService';

export class PlayerManager {
  private storage: JsonStorageService;
  private currentPlayer: Player | null = null;
  private players: Map<string, Player> = new Map();

  constructor() {
    this.storage = new JsonStorageService();
    this.loadPlayers();
  }

  /**
   * 创建新玩家
   */
  async createPlayer(data: Partial<Player> = {}): Promise<Player> {
    const player = createPlayer(data);
    this.players.set(player.id, player);
    await this.savePlayers();
    return player;
  }

  /**
   * 获取玩家
   */
  getPlayer(id: string): Player | null {
    return this.players.get(id) || null;
  }

  /**
   * 获取当前玩家
   */
  getCurrentPlayer(): Player | null {
    return this.currentPlayer;
  }

  /**
   * 设置当前玩家
   */
  setCurrentPlayer(player: Player): void {
    this.currentPlayer = player;
  }

  /**
   * 更新玩家信息
   */
  async updatePlayer(id: string, updates: Partial<Player>): Promise<Player | null> {
    const player = this.players.get(id);
    if (!player) return null;

    const updatedPlayer = { ...player, ...updates, updatedAt: new Date().toISOString() };
    this.players.set(id, updatedPlayer);
    await this.savePlayers();

    // 如果更新的是当前玩家，也更新当前玩家引用
    if (this.currentPlayer && this.currentPlayer.id === id) {
      this.currentPlayer = updatedPlayer;
    }

    return updatedPlayer;
  }

  /**
   * 删除玩家
   */
  async deletePlayer(id: string): Promise<boolean> {
    const deleted = this.players.delete(id);
    if (deleted) {
      await this.savePlayers();
      
      // 如果删除的是当前玩家，清空当前玩家
      if (this.currentPlayer && this.currentPlayer.id === id) {
        this.currentPlayer = null;
      }
    }
    return deleted;
  }

  /**
   * 获取所有玩家
   */
  getAllPlayers(): Player[] {
    return Array.from(this.players.values());
  }

  /**
   * 根据用户名查找玩家
   */
  findPlayerByUsername(username: string): Player | null {
    return Array.from(this.players.values()).find(p => p.username === username) || null;
  }

  /**
   * 根据邮箱查找玩家
   */
  findPlayerByEmail(email: string): Player | null {
    return Array.from(this.players.values()).find(p => p.email === email) || null;
  }

  /**
   * 更新玩家统计信息
   */
  async updatePlayerStats(playerId: string, statUpdates: Partial<PlayerStats>): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedStats = { ...player.stats, ...statUpdates };
    return await this.updatePlayer(playerId, { stats: updatedStats });
  }

  /**
   * 更新玩家偏好设置
   */
  async updatePlayerPreferences(playerId: string, preferenceUpdates: Partial<PlayerPreferences>): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedPreferences = { ...player.preferences, ...preferenceUpdates };
    return await this.updatePlayer(playerId, { preferences: updatedPreferences });
  }

  /**
   * 增加玩家经验
   */
  async addExperience(playerId: string, experience: number): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const newExperience = player.experience + experience;
    const levelProgress = this.calculateLevelProgress(newExperience, player.level);
    
    return await this.updatePlayer(playerId, { 
      experience: newExperience,
      levelProgress 
    });
  }

  /**
   * 增加玩家金币
   */
  async addCoins(playerId: string, coins: number): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const newCoins = Math.max(0, player.coins + coins);
    return await this.updatePlayer(playerId, { coins: newCoins });
  }

  /**
   * 增加玩家宝石
   */
  async addGems(playerId: string, gems: number): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const newGems = Math.max(0, player.gems + gems);
    return await this.updatePlayer(playerId, { gems: newGems });
  }

  /**
   * 添加好友
   */
  async addFriend(playerId: string, friendId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    if (player.friendList.includes(friendId)) {
      return player; // 已经是好友
    }

    const updatedFriendList = [...player.friendList, friendId];
    return await this.updatePlayer(playerId, { friendList: updatedFriendList });
  }

  /**
   * 移除好友
   */
  async removeFriend(playerId: string, friendId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedFriendList = player.friendList.filter(id => id !== friendId);
    return await this.updatePlayer(playerId, { friendList: updatedFriendList });
  }

  /**
   * 添加成就
   */
  async addAchievement(playerId: string, achievementId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    if (player.achievementList.includes(achievementId)) {
      return player; // 已拥有该成就
    }

    const updatedAchievementList = [...player.achievementList, achievementId];
    return await this.updatePlayer(playerId, { achievementList: updatedAchievementList });
  }

  /**
   * 开始案件
   */
  async startCase(playerId: string, caseId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    return await this.updatePlayer(playerId, { 
      currentCaseId: caseId,
      lastActiveAt: new Date().toISOString()
    });
  }

  /**
   * 完成案件
   */
  async completeCase(playerId: string, caseId: string, score: number, timeSpent: number): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedStats = {
      ...player.stats,
      totalCases: player.stats.totalCases + 1,
      solvedCases: player.stats.solvedCases + 1,
      totalScore: player.stats.totalScore + score,
      totalTimeSpent: player.stats.totalTimeSpent + timeSpent,
      currentStreak: player.stats.currentStreak + 1,
      maxStreak: Math.max(player.stats.maxStreak, player.stats.currentStreak + 1)
    };

    // 计算新的平均分和平均时间
    updatedStats.averageScore = Math.round(updatedStats.totalScore / updatedStats.totalCases);
    updatedStats.averageTimePerCase = Math.round(updatedStats.totalTimeSpent / updatedStats.totalCases);

    const updatedCompletedCaseIds = [...player.completedCaseIds, caseId];
    
    return await this.updatePlayer(playerId, { 
      currentCaseId: undefined,
      stats: updatedStats,
      completedCaseIds: updatedCompletedCaseIds,
      lastActiveAt: new Date().toISOString()
    });
  }

  /**
   * 失败案件
   */
  async failCase(playerId: string, caseId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedStats = {
      ...player.stats,
      totalCases: player.stats.totalCases + 1,
      failedCases: player.stats.failedCases + 1,
      currentStreak: 0
    };

    return await this.updatePlayer(playerId, { 
      currentCaseId: undefined,
      stats: updatedStats,
      lastActiveAt: new Date().toISOString()
    });
  }

  /**
   * 收藏案件
   */
  async favoriteCase(playerId: string, caseId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    if (player.favoriteCaseIds.includes(caseId)) {
      return player; // 已收藏
    }

    const updatedFavoriteCaseIds = [...player.favoriteCaseIds, caseId];
    return await this.updatePlayer(playerId, { favoriteCaseIds: updatedFavoriteCaseIds });
  }

  /**
   * 取消收藏案件
   */
  async unfavoriteCase(playerId: string, caseId: string): Promise<Player | null> {
    const player = this.players.get(playerId);
    if (!player) return null;

    const updatedFavoriteCaseIds = player.favoriteCaseIds.filter(id => id !== caseId);
    return await this.updatePlayer(playerId, { favoriteCaseIds: updatedFavoriteCaseIds });
  }

  /**
   * 更新最后活跃时间
   */
  async updateLastActive(playerId: string): Promise<Player | null> {
    return await this.updatePlayer(playerId, { 
      lastActiveAt: new Date().toISOString(),
      isOnline: true
    });
  }

  /**
   * 玩家登出
   */
  async logoutPlayer(playerId: string): Promise<Player | null> {
    return await this.updatePlayer(playerId, { 
      isOnline: false,
      sessionId: undefined
    });
  }

  /**
   * 获取排行榜
   */
  getLeaderboard(limit: number = 10, sortBy: keyof PlayerStats = 'totalScore'): Player[] {
    return Array.from(this.players.values())
      .sort((a, b) => (b.stats[sortBy] as number) - (a.stats[sortBy] as number))
      .slice(0, limit);
  }

  /**
   * 获取在线玩家
   */
  getOnlinePlayers(): Player[] {
    return Array.from(this.players.values()).filter(p => p.isOnline);
  }

  /**
   * 计算等级进度
   */
  private calculateLevelProgress(experience: number, level: any): number {
    // 这里可以引入Player实体中的calculateLevelProgress函数
    const levelThresholds = {
      novice: 0,
      amateur: 100,
      professional: 500,
      expert: 1500,
      master: 3000
    };
    
    const currentThreshold = levelThresholds[level as keyof typeof levelThresholds];
    const nextLevel = this.getNextLevel(level);
    const nextThreshold = nextLevel ? levelThresholds[nextLevel as keyof typeof levelThresholds] : currentThreshold * 2;
    
    if (experience >= nextThreshold) return 100;
    if (experience <= currentThreshold) return 0;
    
    return Math.round(((experience - currentThreshold) / (nextThreshold - currentThreshold)) * 100);
  }

  /**
   * 获取下一等级
   */
  private getNextLevel(currentLevel: any): string | null {
    const levels = ['novice', 'amateur', 'professional', 'expert', 'master'];
    const currentIndex = levels.indexOf(currentLevel);
    return currentIndex < levels.length - 1 ? levels[currentIndex + 1] : null;
  }

  /**
   * 保存玩家数据
   */
  private async savePlayers(): Promise<void> {
    const playersData = Array.from(this.players.values());
    await this.storage.save('players', playersData);
  }

  /**
   * 加载玩家数据
   */
  private async loadPlayers(): Promise<void> {
    try {
      const playersData = await this.storage.load<Player[]>('players');
      if (playersData && Array.isArray(playersData)) {
        playersData.forEach(player => {
          this.players.set(player.id, player);
        });
      }
    } catch (error) {
      console.warn('Failed to load players:', error);
      this.players = new Map();
    }
  }

  /**
   * 重置管理器
   */
  reset(): void {
    this.players.clear();
    this.currentPlayer = null;
  }
}